package com.bms.cfcmms.core.util;

import com.bms.cfcmms.core.module.SqlGenerator;
import com.bms.cfcmms.util.SpringUtils;
import com.bms.cfcmms.model.system.module.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipFile;

import javax.persistence.Column;
import javax.persistence.JoinColumn;

/**
 * Created by carl on 2016/4/12.
 */
public class Utils {

    private static final Logger log = LoggerFactory.getLogger(Utils.class);
    public static final String JOIN_COLOUMNS = "join_coloumns"; //可以连接的列
    public static final String COMM_COLOUMNS = "comm_coloumns"; //普通的coloumn
    public static final String QUERY_LIMIT_START = "start";
    public static final String QUERY_LIMIT_LIMIT = "limit";

    private Utils(){
        throw new IllegalAccessError("Utils class");
    }
    public static boolean hasLength(CharSequence str) {
        return str != null && str.length() > 0;
    }

    /**
     * 获取字段名.
     * <p>
     * <p>获取实例对象object中值不为null的所有属性所对应数据库中的字段名</p>
     *
     * @param fields 反射获得的所有字段信息
     * @param object 所操作的实体对象
     * @return 所有字段名的一个list
     */
    public static Map<String, String> hasValueTableCoulmns(Field[] fields, Object object) {

        Map<String, String> coulmns = new HashMap<>();
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                field.setAccessible(true);
                try {
                    fillCoulmns(object, coulmns, field, column);
                } catch (IllegalAccessException e) {
                    log.error("", e);
                }
            }
        }
        return coulmns;
    }

    private static void fillCoulmns(Object object, Map<String, String> coulmns, Field field, Column column) throws IllegalAccessException {
        Object value = field.get(object);
        if (value != null) {
            String filedName = field.getName();
            String columnName = field.getName();
            if (Utils.hasLength(column.name())) {
                columnName = column.name();
            }
            coulmns.put(columnName, filedName);
        }
    }

    /**
     * 获得一个SqlGenerator对象.
     * <p>
     * <p>根据sqlType和对象obj，及其对应的module来生成一个SqlGenerator</p>
     *
     * @param sqlType sql语句类型：select、delete、update等
     * @param obj     保存查询条件的对象
     * @param module  对象对应的module信息
     * @return 一个SqlGenerator的实例
     */
    public static SqlGenerator getSqlGenerator(String sqlType, Object obj, Module module) {
        SqlGenerator sqlGen = new SqlGenerator(sqlType);
        Class<?> classes = obj.getClass();
        Field[] fields = classes.getDeclaredFields();
        try {
            Field startField = classes.getSuperclass().getDeclaredField(Utils.QUERY_LIMIT_START);
            Field limitField = classes.getSuperclass().getDeclaredField(Utils.QUERY_LIMIT_LIMIT);

            startField.setAccessible(true);
            Object value = startField.get(obj);
            if (value != null) {
                sqlGen.setStart((Integer) value);
            }
            limitField.setAccessible(true);
            value = limitField.get(obj);
            if (value != null) {
                sqlGen.setLimit((Integer) value);
            }
        } catch (Exception e) {
            log.warn("", e);
        }
        Map<String, String> hasValueTableCoulmns = Utils.hasValueTableCoulmns(fields, obj);

        sqlGen.setHasValueTableCoulmns(hasValueTableCoulmns);
        sqlGen.setModule(module);
        return sqlGen;
    }

    /**
     * 获得一个SqlGenerator对象.
     * <p>
     * <p>根据sqlType和对象obj，及其对应的module来生成一个SqlGenerator</p>
     *
     * @param sqlType   sql语句类型：select、delete、update等
     * @param obj       保存查询条件的对象
     * @param tableName 对象对应的表名称
     * @return 一个SqlGenerator的实例
     */
    public static SqlGenerator getSqlGenerator(String sqlType, Object obj, String tableName) {

        Module module = new Module();
        module.setTableName(tableName);

        return getSqlGenerator(sqlType, obj, module);
    }

    /**
     * 获取classType中的字段信息.
     * <p>
     * <p>获取classType中的所有对应到数据库中的所有的字段信息</p>
     *
     * @param classType 对象的类
     * @return classType中所有coloumn的Field
     */
    public static Map<String, List<Field>> findAllColoumns(Class classType) {

        Map<String, List<Field>> coloumns = new HashMap<>();

        List<Field> commColoumns = new ArrayList<>();
        List<Field> joinColoumns = new ArrayList<>();
        coloumns.put(Utils.COMM_COLOUMNS, commColoumns);
        coloumns.put(Utils.JOIN_COLOUMNS, joinColoumns);

        //获取所有父类中的Field
        for (Class<?> clazz = classType; clazz != Object.class; clazz = clazz.getSuperclass()) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                fillCommOrJoinColoumns(commColoumns, joinColoumns, field);
            }
        }
        return coloumns;
    }

    private static void fillCommOrJoinColoumns(List<Field> commColoumns,
                                               List<Field> joinColoumns, Field field) {
        Column column = field.getAnnotation(Column.class);
        if (column != null) {
            commColoumns.add(field);
        } else {
            JoinColumn joinColumn = field.getAnnotation(JoinColumn.class);
            if (joinColumn != null) {
                joinColoumns.add(field);
            }
        }
    }

    /**
     * 字符串空处理.
     * <p/>
     * 如果字符串长度为0，则返回null
     *
     * @param string 待处理的字符串
     * @return 返回一个字符串
     */
    public static String zeroToNull(String string) {
        if (string == null || string.length() == 0) {
            return null;
        } else {
            return string;
        }
    }

    /**
     * 读取压缩包中文件的内容.
     *
     * @param file 文件
     * @return  文件内容
     */
    public static String readZipFile(File file) {
        try (
            ZipFile zipFile = new ZipFile(file);
        ){
            log.info("file size is:" + zipFile.size());
        } catch (IOException e) {
            log.error(SpringUtils.getMessage("file.create.zipfile.fail", ""), e);
        }
        return file.getName();
    }

}
